package com.jastar.android.game.cannon.engine;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.SurfaceHolder;
import com.jastar.android.game.cannon.model.Cannon;
import com.jastar.android.game.cannon.model.Obstacle;
import com.jastar.android.game.cannon.model.Projectile;
import com.jastar.android.game.cannon.model.Target;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class GameEngine {
    private static final int TARGETS_NUM = 6;
    // 游戏状态
    private boolean isRunning;
    private Thread gameThread;

    // 游戏对象
    private final Cannon cannon;
    private final List<Projectile> projectiles;
    private final List<Target> targets;
    private final List<Obstacle> obstacles;

    // 渲染相关
    private SurfaceHolder surfaceHolder;
    private final Paint paint;

    // 游戏数据
    private final Random random = new Random();
    private int score;
    private int canvasWidth, canvasHeight;
    private int obstacleNum = 0;
    private int remainingProjectiles = 20;

    public GameEngine() {
        cannon = new Cannon(50, 50);
        projectiles = new ArrayList<>();
        targets = new ArrayList<>();
        obstacles = new ArrayList<>();
        paint = new Paint();
        paint.setTextSize(32);
    }

    public void setSurfaceHolder(SurfaceHolder holder) {
        this.surfaceHolder = holder;
    }

    public void setCanvasSize(int width, int height) {
        this.canvasWidth = width;
        this.canvasHeight = height;
        cannon.setPosition(width * 0.1f, height / 2f);
        targets.clear();
        createTargets();
    }

    private void createTargets() {
        obstacles.clear();
        if (0 == canvasWidth || 0 == canvasHeight) return;
        for (int i = targets.size(); i < TARGETS_NUM; i++) {
            float x = random.nextFloat() * canvasWidth * 0.5f + canvasWidth * 0.5f;
            float y = random.nextFloat() * canvasHeight * 0.6f + canvasHeight * 0.2f;
            Target newTarget = Target.random(x, y);
            boolean isCollision = false;
            for (Target t : targets) {
                if (newTarget.checkCollision(t.getX(), t.getY(), t.getRadius())) {
                    isCollision = true;
                    break;
                }
            }
            if (!isCollision) targets.add(newTarget);
            else i--;
        }

        // 生成障碍物
        for (int i = 0; i < obstacleNum; i++) {
            float x = random.nextFloat() * canvasWidth * 0.3f + canvasWidth * 0.5f;
            float y = random.nextFloat() * canvasHeight * 0.6f + canvasHeight * 0.2f;
            int w = random.nextInt(40) + 20;
            int h = random.nextInt(80) + 40;
            Obstacle newObstacle = new Obstacle(x, y, w, h, 1);

            boolean isCollision = false;
            // 检查与目标的碰撞
            for (Target t : targets) {
                if (newObstacle.checkCollision(t.getX(), t.getY(), t.getRadius())) {
                    isCollision = true;
                    break;
                }
            }

            if (!isCollision) obstacles.add(newObstacle);
            else i--;
        }
        if (obstacleNum < TARGETS_NUM) obstacleNum++; //每次新增一个障碍物，最多和靶数相等
    }

    public void start() {
        if (isRunning && gameThread != null && gameThread.isAlive()) stop();
        isRunning = true;
        gameThread = new Thread(this::gameLoop);
        gameThread.start();
    }

    public void stop() {
        isRunning = false;
        try {
            if (gameThread != null) {
                gameThread.join(100); // 添加超时时间
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        gameThread = null; // 重置线程引用
    }

    public void pause() {
        isRunning = false;
    }

    public void resume() {
        isRunning = true;
    }

    private void gameLoop() {
        long lastTime = System.currentTimeMillis();
        final long frameTime = 1000 / 60; // 60 FPS

        while (isRunning) {
            long currentTime = System.currentTimeMillis();
            long elapsedTime = currentTime - lastTime;

            if (elapsedTime >= frameTime) {
                update(elapsedTime / 1000f);
                render();
                lastTime = currentTime;
            }
        }
    }

    private void update(float deltaTime) {
        refreshCharging();
        // 更新所有炮弹
        for (Projectile projectile : projectiles) {
            projectile.update(deltaTime);

            // 检查是否超出屏幕
            if (projectile.getX() < 0 || projectile.getX() > canvasWidth || projectile.getY() > canvasHeight) {
                projectile.setActive(false);
            }
        }

        // 碰撞检测
        for (Projectile projectile : projectiles) {
            if (!projectile.isActive()) continue;

            for (Target target : targets) {
                if (target.isHit()) continue;

                if (target.checkCollision(projectile.getX(), projectile.getY(), projectile.getRadius())) {
                    score += target.getScore();
                    target.setHit(true);
                    projectile.setActive(false);
                    break;
                }
            }

            for (Obstacle obstacle : obstacles) {
                if (obstacle.checkCollision(projectile.getX(), projectile.getY(), projectile.getRadius())) {
                    projectile.setActive(false);
                    break;
                }
            }
        }

        // 清理非活跃对象
        projectiles.removeIf(p -> !p.isActive());
        targets.removeIf(Target::isHit);

        // 补充新目标
        if (targets.size() < 1) {
            createTargets();
            remainingProjectiles += 20;
        }
    }

    private void render() {
        Canvas canvas = surfaceHolder.lockCanvas();
        if (canvas == null) return;

        try {
            // 清空画布
            canvas.drawColor(Color.WHITE);

            // 绘制游戏对象
            cannon.draw(canvas);

            for (Projectile projectile : projectiles) {
                projectile.draw(canvas);
            }

            for (Target target : targets) {
                if (!target.isHit()) {
                    target.draw(canvas);
                }
            }

            for (Obstacle obstacle : obstacles) {
                obstacle.draw(canvas);
            }

            if (isGameOver()) {
                paint.setColor(Color.RED);
                paint.setTextSize(42);
                canvas.drawText("游戏结束，最终得分: " + score, 20, 50, paint);
            } else {
                paint.setColor(Color.BLUE);
                canvas.drawText("得分: " + score, 20, 40, paint);
                paint.setColor(0xFF666666);
                canvas.drawText("炮弹: " + remainingProjectiles, 20, 100, paint);
            }
        } finally {
            surfaceHolder.unlockCanvasAndPost(canvas);
        }
    }

    private float MAX_CHARGE_TIME = 1.5F;
    private long chargeStartTime;
    private boolean isCharging;

    public void startCharging() {
        if (remainingProjectiles <= 0) return;
        if (isCharging) return;
        chargeStartTime = System.currentTimeMillis();
        isCharging = true;
    }

    public void refreshCharging() {
        if (!isCharging) return;
        long chargeDuration = System.currentTimeMillis() - chargeStartTime;
        float chargeSecond = Math.min(chargeDuration / 1000f, MAX_CHARGE_TIME);
        float power = 100 / MAX_CHARGE_TIME * chargeSecond;
        cannon.setPower(power);
    }

    public void fireProjectile() {
        if (remainingProjectiles <= 0) return;
        refreshCharging();

        float angle = cannon.getAngle();
        float startX = cannon.getX() + cannon.getBarrelLength() * (float) Math.cos(Math.toRadians(angle));
        float startY = cannon.getY() - cannon.getBarrelLength() * (float) Math.sin(Math.toRadians(angle));

        Projectile projectile = new Projectile(startX, startY, angle, cannon.getPower());
        projectiles.add(projectile);
        remainingProjectiles--;

        isCharging = false;
        cannon.setPower(0);
    }

    //剩余炮弹为0，且炮弹全部落地
    public boolean isGameOver() {
        return remainingProjectiles <= 0 && projectiles.isEmpty();
    }

    public Cannon getCannon() {
        return cannon;
    }

}